from django.utils.decorators import method_decorator
from django.utils.deprecation import MiddlewareMixin
from mydjango.settings import SECRET_KEY
from qiniu import Auth
from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图

from django.views import View

# from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid
import redis
import base64
from hashlib import sha256
import hmac
import urllib
import re
from myapp.myser import UserSer, PicsSer, GoodsSer, CateSer, CommentSer
from myapp.models import User, Pics, Goods, Cate, Comment, UserFlow
from django.core.paginator import Paginator
import pymongo
from bson import json_util as jsonb  # 导入bson
# IP和端口

host = 'localhost'
port = 6379

# host = '192.168.99.100'
# port = 6380

# 链接对象
r = redis.Redis(host=host, port=port)

mongo_client = pymongo.MongoClient(host='127.0.0.1', port=27017)  # mongo的链接对象


class GoodsSearch(APIView):  # 商品检索接口
    
    def get(self, request):
        # 接收餐位数
        word = request.GET.get('word', None)
        goodslist = Goods.objects.filter(Q(name__contains= word)| Q(desc__icontains= word))  # 模糊查询
        goods_ser = GoodsSer(goodslist, many=True)  # 序列化
        return Response(goods_ser.data)
        

def get_top_n(num):  # 获取前n名的数据
    goods_click = r.zrange('good_rank', 0,-1, desc=True, withscores=True)[:num] # 获取redis数据
    goods = Goods.objects.in_bulk([int(item[0]) for item in goods_click])
    res = []  # 合并操作
    for item in goods_click:
        try:
            res.append({int(item[1]):goods[int(item[0])]})
        except Exception as e:
            pass
    return res
 
 
class GoodsRank(APIView):
    
    def get(self, request):
        get_res= get_top_n(10)  # 获取前n数据
        res = []
        for dic in get_res:  # 遍历进行序列化
            for k,v in dic.items():
                data = GoodsSer(v).data  # 序列化该商品
                data['clicks'] = k  # 将商品点击数附加到商品数据中
                res.append(data)
        return Response(res)
        
            

class GoodsClick(APIView):   # 新的商品参与排名
    def get(self, request):
        gid = request.GET.get('gid')
        r.zincrby('good_rank', 1, int(gid))
        return Response({
            'code': 200,
            'message': '访问+1'
        })
        


def dictfetchall(cursor):  # 美化
    desc = cursor.description  # 获取游标描述
    return [
        dict(zip([col[0] for col in desc], row))
        for row in cursor.fetchall()
    ]


class AddUserFlow(APIView):  # 添加商品收藏

    def get(self, request):
        uid = request.GET.get('uid')
        gid = request.GET.get('gid')
        type = request.GET.get('type',None)
        # userflow = UserFlow.objects.filter(gid=int(gid)).first()
        if type == '1':
            try:
                userflow = UserFlow.objects.create(uid=int(uid), gid=int(gid))
                goods = Goods.objects.filter(id=int(gid)).first()
                goods.flow = goods.flow + 1
                goods.save()
                return Response({
                    'code': 200,
                    'message': '添加收藏成功'
                })
            except Exception as e:
                return Response({
                    'code': 201,
                    'message': '不能重复收藏'
                })
                
        elif type == '0':
            UserFlow.objects.filter(uid=int(uid), gid=int(gid)).delete()
            goods = Goods.objects.filter(id=int(gid)).first()
            goods.flow = goods.flow - 1
            goods.save()
            return Response({
                'code': 202,
                'message': '取关成功'
            })
        elif type == '2':  # 批量删除
            ids = request.GET.get('ids')
            UserFlow.objects.filter(uid=int(uid)).delete()
            id_list = eval(ids)# 强转
            for id in id_list:
                userflow = UserFlow(gid=int(id), uid=int(uid))
                userflow.save()
            return Response({
                'code': 200,
                'message': '批量删除成功'
            })
        elif type == '3':
            ids = request.GET.get('ids')
            id_list = eval(ids)
            for id in id_list:
                userflow = UserFlow.objects.filter(gid=int(id), uid=int(uid)).delete()
            return Response({
                'code': 200,
                'message': '批量删除成功'
            })
        else:
            userflow = UserFlow.objects.filter(uid= int(uid), gid= int(gid))
            if userflow:   
                return Response({
                    'code': 200,
                    'message': '已收藏'
                })
            else:
                return Response({
                    'code': 200,
                    'message': '收藏'
                })


class GidFlow(View):  # 获取该商品已关注的人数

    def get(self, request):
        gid = request.GET.get('gid')
        cursor = connection.cursor()
        cursor.execute('select a.username from user a left join userflow b on a.id = b.uid where b.gid = %s' % str(gid))
        # result = cursor.fetchall()  # 获取结果
        result = dictfetchall(cursor)
        return HttpResponse(json.dumps(result, ensure_ascii=False, indent=4), content_type='application/json')
    


class UidFlow(View):  # 用户关注了那些商品

    def get(self, request):
        uid = request.GET.get('uid')
        cursor = connection.cursor()  # 建立游标对象
        cursor.execute('select a.id, a.name from goods a left join userflow b on a.id = b.gid where b.uid = %s' % str(uid))  # 执行sql语句
        # result = cursor.fetchall()  # 获取结果
        result = dictfetchall(cursor)  # 美化之后
        return HttpResponse(json.dumps(result, ensure_ascii=False), content_type='application/json')


class Page_CommentList(APIView):  # 评论分页器

    def get(self, request):
        id = request.GET.get('id')
        page = int(request.GET.get('page', 1))
        size = int(request.GET.get('size', 1))
        data_start = (page-1) * size
        data_end = page * size
        commentlist = Comment.objects.filter(gid=int(id)).order_by('-id')[data_start:data_end]
        count = Comment.objects.filter(gid=int(id)).count()
        comment_ser = CommentSer(commentlist, many=True)
        return Response({
            'code': 200,
            'data': comment_ser.data,
            'total': count
        })


class CommentList(APIView):  # 评论展示

    def get(self, request):
        id = request.GET.get('id')  # 获取用户id
        comment = Comment.objects.filter(gid=int(id)).order_by('-id')  # 查询商品
        comment_ser = CommentSer(comment, many=True)  # 序列化
        return Response(comment_ser.data)


class InsertComment(APIView):  # 反序列化入库(商品评论)

    def post(self, request):
        uid = request.POST.get('uid')
        if r.get(str(uid)):
            return Response({
                'code': 200,
                'message': '您评论过快，请歇息片刻'
            })

        comment = CommentSer(data=request.data)  # 初始化参数
        if comment.is_valid():  # 数据校验
            comment.save()  # 入库

            # 插入评论标记
            r.set(str(uid), '123')
            r.expire(str(uid), 30)
        return Response({
            'code': 200,
            'message': '评论成功'
        })

    # def post(self, request):  #mongo
    #     comment = request.data
    #     db = mongo_client.md  # 建立数据库对象
    #     table = db.comment  # 建立表对象
    #     res = table.find({'comment': comment}).count()  # 排重
    #     if res > 0:
    #         return Response({'message': '数据重复'})
    #     else:
    #         table.insert({'comment': comment})  # 入库操作
    #         return Response({
    #             'code': 200,
    #             'message': '标签入库成功'
    #         })


class AccessRight(MiddlewareMixin):  # 中间件设置访问次数

    def process_request(self, request):
        if re.match(r'/goodslist/', request.path):
            # print('匹配了路由')
            if 'HTTP_X_FORWARDED_FOR' in request.META:
                ip = request.META.get('HTTP_X_FORWARDED_FOR')
            else:
                ip = request.META.get('REMOTE_ADDR')
            if ip not in r.smembers('accessright'):  # 判断该用户是否恶意刷新访问量
                # print('代码执行到这里')
                r.sadd('accessright', ip)  # 保存此ip到accessright中
                # 时效为60秒，保存到数据库中。后期调用查看在线人数的时候，可以查看accessright数量即可
                r.expire('accessright', 60)
        else:
            # print('代码执行到这里')
            pass


class GetOnLine(APIView):  # 统计在线人数

    def get(self, request):
        # 获取客户ip
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip = request.META.get('HTTP_X_FORWARDED_FOR')
        else:
            ip = request.META.get('REMOTE_ADDR')
        r.sadd('online', ip)
        r.expire('online', 20)
        myset = r.smembers('online')
        return Response({
            'code': 200,
            'online': len(myset)
        })


class UpdTag(APIView):  # 修改标签
    def get(self, request):
        id = request.GET.get('id', None)
        tags = request.GET.get('tags', None)
        tags = tags.split(',')
        db = mongo_client.md
        table = db.tags
        table.update({'gid': str(id)}, {"$set": {'tags': tags}})  # 修改mongo数据
        return Response({
            'code': 200,
            'message': '标签修改成功'
        })


class UpdGood(APIView):  # 修改商品信息
    def get(self, request):
        id = request.GET.get('id')
        name = request.GET.get('name')
        desc = request.GET.get('desc')
        parms = request.GET.get('parms')
        price = request.GET.get('price')
        cate_id = request.GET.get('cate_id')
        good = Goods.objects.filter(id=id).update(
            name=name, desc=desc, parms=parms, price=price, cate_id=cate_id)  # 修改mysql中的商品数据
        if good:
            return Response({
                'code': 200,
                'message': '商品信息修改成功'
            })
        else:
            return Response({
                'code': 200,
                'message': '商品信息修改失败'
            })


class GetTags(View):  # 获取标签

    def get(self, request):
        id = request.GET.get('id', None)
        db = mongo_client.md  # 建立数据库对象
        table = db.tags  # 建立表对象
        res = table.find_one({'gid': str(id)}, {'_id': 0})
        return HttpResponse(jsonb.dumps(res, ensure_ascii=False))

        # redis_tag = list(r.smembers(str(id))) # redis获取标签
        # redis_tag = (redis_tag[0].decode('utf-8')).split(',')
        # return HttpResponse(json.dumps({
        #     'code': 200, 'tags': redis_tag}))


class InsertTags(APIView):  # 存储标签 mongo存储

    def get(self, request):
        id = request.GET.get('id', None)
        tags = request.GET.get('tags', None)
        # tags = tags.replace('，', ',')  # 利用heiui的TagInput标签 不需要替换 已废除
        tags = tags.split(',')

        db = mongo_client.md  # 建立数据库对象
        table = db.tags  # 建立表对象
        res = table.find({'gid': str(id)}).count()  # 排重
        if res > 0:
            return Response({'message': '数据重复'})
        else:
            table.insert({'gid': str(id), 'tags': tags})  # 入库操作
            return Response({
                'code': 200,
                'message': '标签入库成功'
            })

        # redis_tag = ','.join(tags)  # 存储在redis数据库中
        # r.sadd(str(id), str(redis_tag))
        # return Response({
        #     'code': 200,
        #     'message': 'redis数据库存储成功'
        # })


class GoodItem(APIView):  # 获取商品信息
    def get(self, request):
        id = request.GET.get('id')
        good = Goods.objects.get(id=id)
        good_ser = GoodsSer(good)
        return Response(good_ser.data)


class GoodsList(APIView):  # 商品分页展示
    def get(self, request):
        page = int(request.GET.get('page', 1))  # 当前页
        size = int(request.GET.get('size', 1))  # 一页有多少条商品
        data_start = (page-1) * size  # 定义从那开始切
        data_end = page * size  # 定义切到那
        goodslist = Goods.objects.all()[data_start:data_end]  # 查询数据
        count = Goods.objects.count()  # 查询总数
        goods_ser = GoodsSer(goodslist, many=True)  # 序列化
        return Response({
            'code': 200,
            'data': goods_ser.data,
            'total': count
        })


class InserGoods(APIView):  # mysql 存储
    def get(self, request):
        name = request.GET.get('name')
        desc = request.GET.get('desc')
        parms = request.GET.get('parms')
        price = request.GET.get('price')
        cate_id = request.GET.get('cate_id')
        img = request.GET.get('img', '')
        image = request.GET.get('image', '')

        goods = Goods.objects.filter(name=name).first()

        if goods:
            return Response({
                'code': 405,
                'data': '该商品已存在'
            })
        Goods.objects.create(name=name, desc=desc, parms=parms, price=price,
                             cate_id=cate_id, img=img, video=image)  # mysql存储
        good_id = Goods.objects.get(name=name)

        return Response({
            'id': good_id.id,
            'code': 200,
            'data': '商品添加成功'
        })


# class InserGoods(APIView):  # redis存储
#     def get(self, request):
#         name = request.GET.get('name')
#         desc = request.GET.get('desc')
#         parms = request.GET.get('parms')
#         price = request.GET.get('price')
#         cate_id = request.GET.get('cate_id')

#         try:
#             redis_goods = r.get(name).decode('utf-8')
#             # cc = redis_goods.replace('\'', '\"')  # 获取redis数据库中的数据  是否能使用
#             # print(cc)
#             # cc = json.loads(cc)
#             # print(cc)
#             if redis_goods:
#                 return Response({
#                     'code': 405,
#                     'data': '该商品已存在'
#                 })

#         except Exception as e:
#             print(e)

#         redis_dict = {"name": name, "desc": desc,
#                       "parms": parms, "price": price, "cate_id": cate_id}
#         r.set(name, str(redis_dict))

#         return Response({
#             'code': 200,
#             'data': '商品添加成功'
#         })
